using IM.Easy.Infrastructure.Query;
using Microsoft.AspNetCore.Mvc;
using IM.Easy.ScheduledServices.Dtos;
using IM.Easy.ScheduledServices.IServices;
using IM.Easy.Entity.Scheduled;
using IM.Easy.Core.Attributes;
using Mapster;
using Quartz;
using IM.Easy.Core.Utils;
using IM.Easy.ScheduledServices;

namespace IM.Easy.Api.Controllers.Scheduled
{
    /// <summary>
    /// ScheduledJobController 控制器
    /// </summary>
    public class ScheduledJobController : ControllerBase
    {
        private readonly IScheduledJobService _service;
        private readonly IJobTriggerService _triggerService;
        private readonly ISchedulerService _schedulerService;

        /// <summary>
        /// 构造函数，注入服务
        /// </summary>
        /// <param name="service">服务接口</param>
        public ScheduledJobController(IScheduledJobService service, IJobTriggerService triggerService, ISchedulerService schedulerService)
        {
            _service = service;
            _triggerService = triggerService;
            _schedulerService = schedulerService;
        }

        /// <summary>
        /// 获取所有ScheduledJob对象
        /// </summary>
        /// <returns>返回ScheduledJob列表</returns>
        [HttpGet]
        [Api(Name = "获取任务计划列表", Perm = "schedule:job:list")]
        public PageResponse<ScheduledJobDto> GetList([FromQuery] ScheduledJobQueryDto query)
        {
            return _service.GetPageList(query);
        }

        /// <summary>
        /// 根据ID获取ScheduledJob对象
        /// </summary>
        /// <param name="id">对象的ID</param>
        /// <returns>返回指定的ScheduledJob对象</returns>
        [HttpGet("{id}")]
        [Api(Name = "获取任务计划", Perm = "schedule:job:info")]
        public ScheduledJobDto GetById([FromRoute] Guid id)
        {
            var instance = _service.GetScheduled(id) ?? throw new KeyNotFoundException($"未找到ID为 {id} 的ScheduledJob对象。");
            var result = instance.Adapt<ScheduledJobDto>();
            return result;
        }

        /// <summary>
        /// 创建新的ScheduledJob对象
        /// </summary>
        /// <param name="entity">要创建的ScheduledJob对象</param>
        /// <returns>返回创建后的ScheduledJob对象</returns>
        [HttpPost]
        [Api(Name = "添加任务计划", Perm = "schedule:job:add")]
        public async Task<ScheduledJob> Create([FromBody] ScheduledJobCreateDto entity)
        {
            //过滤请求参数为空的情况
            entity.Extend.Params = entity.Extend.Params
                                        .Where(s => !string.IsNullOrWhiteSpace(s.Key) && !string.IsNullOrWhiteSpace(s.Value))
                                        .ToList();
            var job = _service.Create(entity);
            await _schedulerService.NewScheduler(job);

            if (job.Trigger.StartMode == TriggerStartMode.Immediate || job.Trigger.StartMode == TriggerStartMode.Scheduled)
            {
                var nextFireTime = await _schedulerService.StartScheduler(job.Trigger);
                _service.Update(s => new ScheduledJob { NextFireTime = nextFireTime.LocalDateTime, Status = SchedulerStatus.Normal }, s => s.Id == job.Id);
            }
            return job;
        }

        /// <summary>
        /// 修改任务基本信息
        /// </summary>
        /// <param name="id">对象的ID</param>
        /// <param name="entity">更新后的ScheduledJob对象</param>
        [HttpPut]
        [Api(Name = "更新任务计划", Perm = "schedule:job:add")]
        public void Update([FromBody] ScheduledJob entity)
        {
            _service.Update(entity);
        }

        /// <summary>
        /// 批量删除ScheduledJob对象
        /// </summary>
        /// <param name="ids">对象的IDS</param>
        [HttpDelete]
        [Api(Name = "删除任务计划", Perm = "schedule:job:del")]
        public async Task Delete([FromBody] Guid[] ids)
        {
            _service.Delete(ids);
            var schedulerIds = Array.ConvertAll(ids, guid => guid.ToString());
            await _schedulerService.RemoveSchedulers(schedulerIds);
        }

        /// <summary>
        /// 启动任务
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Api(Name = "启动任务计划", Perm = "schedule:job:start")]
        [HttpPut("start/{id}")]
        public async Task Start([FromRoute] Guid id)
        {
            var job = _service.GetScheduled(id);
            var nextFireTime = await _schedulerService.StartScheduler(job.Trigger);
            _service.Update(s => new ScheduledJob { NextFireTime = nextFireTime.LocalDateTime, Status = SchedulerStatus.Normal }, s => s.Id == id);
        }

        /// <summary>
        /// 暂停任务计划
        /// </summary>
        /// <returns></returns>
        [HttpPut("pause/{id}")]
        [Api(Name = "暂停任务计划", Perm = "schedule:job:pause")]
        public async Task Pause([FromRoute] Guid id)
        {
            var job = _service.GetScheduled(id);
            if (job.Status != SchedulerStatus.Normal) ExceptionUtils.ThrowBusinessException("当前状态不允许暂停");
            job.Status = SchedulerStatus.Paused;
            _service.Update(job);
            var trigger = job.Trigger;
            await _schedulerService.PauseScheduler(trigger.Id.ToString());
        }

        /// <summary>
        /// 恢复任务计划
        /// </summary>
        /// <returns></returns>
        [HttpPut("resume/{id}")]
        [Api(Name = "恢复任务计划", Perm = "schedule:job:resume")]
        public async Task Resume([FromRoute] Guid id)
        {
            var job = _service.GetScheduled(id);
            if (job.Status != SchedulerStatus.Paused) ExceptionUtils.ThrowBusinessException("当前状态不允许启动");
            job.Status = SchedulerStatus.Normal;
            _service.Update(job);
            var trigger = job.Trigger;
            await _schedulerService.ResumeScheduler(trigger.Id.ToString());
        }

        /// <summary>
        /// 单独执行一次
        /// </summary>
        /// <returns></returns>
        [HttpPut("trigger/once/{id}")]
        [Api(Name = "执行任务计划", Perm = "schedule:job:excute")]
        public async Task TriggerOnce([FromRoute] Guid id)
        {
            await _schedulerService.TriggerOnce(id.ToString());
        }

        /// <summary>
        /// 获取可用程序集
        /// </summary>
        [HttpGet("jobtype/avail")]
        [Api(Name = "获取可用作业程序集", AllowAnonymous = true)]
        public List<JobOption> GetAvailableJobs()
        {
            var availables = JobScanner.FindAllJobs();
            return availables;
        }
    }
}
